/*  
    This file is part of the Arctic Fox Code Tree (AFCT).
    Copyright 2002, Arctic Fox Computer Consulting Inc.

    AFCT is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    AFCT is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with AFCT; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

package org.afox.util.validators.string;

import org.afox.util.validators.*;
import java.util.*;

public final class StringValidatorFactory
{
	private static Hashtable cache = new Hashtable();

/**
   This method returns a standard validator for passwords.  This validator will only validate passwords
   which are:
   <UL>
   <LI> Minimum of 6 characters </LI>
   <LI> Maxiumum of 48 characters </LI>
   <LI> Contains only printable characters </LI>
   </UL>

   <P> Also, passwords cannot contain:
   <UL>
   <LI> the ' character.  This character will cause problems with SQL statements </LI>
   <LI> the \ character.  This character is often used for quoting purposes </LI>
   <LI> the -- character sequence.  This is the comment sequence for SQL. </LI>
   </UL>
 */
	public static Validator getPasswordValidator()
	{
		if (cache.get("Password")!=null)
			return (Validator) cache.get("Password");

		// Business rules for password length
		Validator theValidator = new MinLengthValidator(6);
		Validator temp = new MaxLengthValidator(theValidator, 48);

		// only allow printable characters
		temp = new ValidCharRangeValidator(temp, 32,126);

		// Do not allow ' and \ 
		temp = new InvalidCharValidator(temp, "'\\");

		// -- is SQL comment character sequence.  Embedded within a password could cause problems
		// if an attempt is made to put email address in database.
		temp = new InvalidSequenceExactValidator(temp, "--");

		cache.put("Password", theValidator);
		return theValidator;
	}

/**
   This method returns a standard validator for email addresses. This method implements a portion of the
   standard defined in RFC822.  The subset implemented is as follows

   <PRE>
   addr-spec = local-part "@" domain
   local-part = word *("." word)
   domain = sub-domain *("." subdomain)
   sub-domain = word
   word = *(any char except specials, SPACE and CTLs)
   specials = ()<>@,;:\.[]
   </PRE>

   <P> To put this in more readable terms:
   <UL>
   <LI> Addresses are at least 5 characters in length (x@y.z)
   <LI> Addresses cannot contain the following characters: ()<>,;:\[]
   <LI> Addresses cannot contain the ' (single quote) for SQL security
   <LI> Addresses cannot contain the -- character sequence for SQL security
   <LI> Addresses cannot start with a @ or .
   <LI> Addresses cannot end with a @ or .
   </UL>

   <P> The RFC defines quoted strings are being part of the email address. We are not concerned with those
   here, so they have been removed.
 */
	public static Validator getEmailAddressValidator()
	{
		if (cache.get("Email")!=null)
			return (Validator) cache.get("Email");

		// min size for email address = x@y.z
		Validator theValidator = new MinLengthValidator(5);

		// Cannot contain the following characters
		Validator temp = new InvalidCharValidator(theValidator, "()<>,;:\\[]' ");

		// -- is SQL comment character sequence.  Embedded within an email address could cause problems
		// if an attempt is made to put email address in database.
		temp = new InvalidSequenceExactValidator(temp, "--");

		// Email address must have an @ followed by a .
		temp = new SequenceValidator(temp, "@.");

		// email address cannot start with an @ or .
		temp = new InvalidStartValidator(temp,"@.");

		// email address cannot start with an @
		temp = new InvalidEndValidator(temp,"@.");

		cache.put("Email", theValidator);
		return theValidator;
	}

/**
   This method returns a validator which will only validate digits
 */
	public static Validator getDigitValidator()
	{
		if (cache.get("Digit")!=null)
			return (Validator) cache.get("Digit");

		Validator theValidator = new ValidCharRangeValidator(48,57);

		cache.put("Digit", theValidator);
		return theValidator;
	}

/**
   This method returns a validator which will only validate alpha characters
 */
	public static Validator getAlphaValidator()
	{
		if (cache.get("Alpha")!=null)
			return (Validator) cache.get("Alpha");

		Validator theValidator = new ValidCharRangeValidator(65,122);
		Validator temp = new InvalidCharRangeValidator(theValidator, 91, 96);

		cache.put("Alpha", theValidator);
		return theValidator;
	}

/**
   This method returns a validator which will only validate Upper-case alpha characters
 */
	public static Validator getUpperCaseValidator()
	{
		if (cache.get("UpperCase")!=null)
			return (Validator) cache.get("UpperCase");

		Validator theValidator = new ValidCharRangeValidator(65,90);

		cache.put("UpperCase", theValidator);
		return theValidator;
	}

/**
   This method returns a validator which will only validate lower-case alpha characters
 */
	public static Validator getLowerCaseValidator()
	{
		if (cache.get("LowerCase")!=null)
			return (Validator) cache.get("LowerCase");

		Validator theValidator = new ValidCharRangeValidator(97,122);

		cache.put("LowerCase", theValidator);
		return theValidator;
	}

/**
   This method returns a validator which will only validate digits and alpha characters
 */
	public static Validator getAlphaNumericValidator()
	{
		if (cache.get("AlphaNumeric")!=null)
			return (Validator) cache.get("AlphaNumeric");

		Validator theValidator = new ValidCharRangeValidator(48,122);
		Validator temp = new InvalidCharRangeValidator(theValidator, 58,64);
		temp = new InvalidCharRangeValidator(temp, 91,96);

		cache.put("AlphaNumeric", theValidator);
		return theValidator;
	}

/**
   This method returns a validator which will only validate printable characters
 */
	public static Validator getPrintableValidator()
	{
		if (cache.get("Printable")!=null)
			return (Validator) cache.get("Printable");

		Validator theValidator = new ValidCharRangeValidator(32,126);

		cache.put("Printable", theValidator);
		return theValidator;
	}


	public static void main(String[] args)
	{
		System.out.println("Password Validator: \n" + getPasswordValidator());
		System.out.println("Email Address Validator: \n" + getEmailAddressValidator());
		System.out.println("Digit Validator: \n" + getDigitValidator());
		System.out.println("Alpha Validator: \n" + getAlphaValidator());
		System.out.println("Upper Case Validator: \n" + getUpperCaseValidator());
		System.out.println("Lower Case Validator: \n" + getLowerCaseValidator());
		System.out.println("Alpha-Numeric Validator: \n" + getAlphaNumericValidator());
	}

}
